/// <license>
/// Copyright (c) 2002-2008, DotNetNuke Corporation
/// All rights reserved
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
/// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
/// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
/// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
/// of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
/// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
/// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
/// DEALINGS IN THE SOFTWARE.
/// </license>

#region Using Statements

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web;
using System.Security.Permissions;
using System.ComponentModel;

using DotNetNuke.ModuleToolkit.Modules.Extensions;
using DotNetNuke.ModuleToolkit.Modules.Skinning.SkinObjects;

#endregion

namespace DotNetNuke.ModuleToolkit.Modules.Skinning
{
    /// -----------------------------------------------------------------------------
    /// <summary>
    /// Provides a base class for a Control Skin
    /// </summary>
    /// <remarks>
    /// This class handles all of the skinning functionality required for a Control Skin.
    /// A <see cref="SkinnedControlHost"/> loads up a different <see cref="SkinnedControl"/>
    /// depending on the currently active skin. 
    /// </remarks>
    /// <history>
    ///     [anurse]    05/02/2006  created
    /// </history>
    /// -----------------------------------------------------------------------------
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal),
    AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
    ToolboxItem(false)
    ]
    public class SkinnedControl : UserControl
    {

        #region Private Fields

        private SkinnedControlHost _host;
        private IList<IExtension> _Extensions;
        private IList<ISkinObject> _skinObjects;

        #endregion

        #region Public Properties

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets the SkinnedControlHost that is hosting this control 
        /// </summary>
        /// <history>
        ///     [anurse]  05/02/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public SkinnedControlHost Host
        {
            get { return _host; }
            internal set { _host = value; }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets the Control that declares the SkinnedControlHost that loaded this control
        /// </summary>
        /// <history>
        ///     [anurse]  05/02/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public Control ParentControl
        {
            get { return _host.ParentControl; }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets a list of Extensions that exist in the control
        /// </summary>
        /// <history>
        ///     [cnurse]  10/11/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public IList<IExtension> Extensions
        {
            get
            {
                if (_Extensions == null)
                    _Extensions = FindExtensions();
                return _Extensions;
            }
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Gets a list of skin objects that exist in the control
        /// </summary>
        /// <history>
        ///     [anurse]  05/02/2006  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public IList<ISkinObject> SkinObjects
        {
            get
            {
                if (_skinObjects == null)
                    _skinObjects = FindSkinObjects();
                return _skinObjects;
            }
        } 

        #endregion

        #region Public Methods

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Finds the control with the specified name and verifies that it is a Extension
        /// </summary>
        /// <param name="name">The name of the skin object to find</param>
        /// <returns>An instance of the skin object, or a null reference (Nothing in VB.net) if no such skin object exists</returns>
        /// <remarks>
        /// Note: If this method returns a null reference (Nothing in VB.net) a control with the name may exist
        /// but it does not implement the <see cref="IExtension"/> interface
        /// </remarks>
        /// <history>
        ///     [cnurse]  10/12/2007  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public IExtension FindExtension(string name)
        {
            ISkinObject skinControl = FindSkinObject(name);
            IExtension ExtensionControl = null;
            if (skinControl is IExtension)
                ExtensionControl = skinControl as IExtension;
            return ExtensionControl;
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Finds the control with the specified name and verifies that it is a SkinObject
        /// </summary>
        /// <param name="name">The name of the skin object to find</param>
        /// <returns>An instance of the skin object, or a null reference (Nothing in VB.net) if no such skin object exists</returns>
        /// <remarks>
        /// Note: If this method returns a null reference (Nothing in VB.net) a control with the name may exist
        /// but it does not implement the <see cref="ISkinObject"/> interface
        /// </remarks>
        /// <history>
        ///     [anurse]  12/22/2005  created
        /// </history>
        /// -----------------------------------------------------------------------------
        public ISkinObject FindSkinObject(string name)
        {
            ISkinObject skinControl = null;
            foreach (ISkinObject skinObject in SkinObjects)
            {
                Control ctrl = skinObject as Control;
                if (ctrl != null && ctrl.ID == name)
                {
                    skinControl = skinObject;
                    break;
                }
            }
            return skinControl;
        }

        #endregion

        #region Private Methods

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Finds all the Extensions in the skin
        /// </summary>
        /// <returns>A List of Extensions in the skin</returns>
        /// <history>
        ///   [cnurse]  10/11/2007   created
        /// </history>
        /// -----------------------------------------------------------------------------
        private IList<IExtension> FindExtensions()
        {
            IList<IExtension> Extensions = new List<IExtension>();
            foreach (ISkinObject skinObject in SkinObjects)
            {
                if (skinObject is IExtension)
                {
                    Extensions.Add(skinObject as IExtension);
                }
            }
            return Extensions;
        }

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Finds all the SkinObjects in the skin
        /// </summary>
        /// <returns>A List of SkinObjects in the skin</returns>
        /// <history>
        ///   [anurse]  1/14/2006   created
        /// </history>
        /// -----------------------------------------------------------------------------
        private IList<ISkinObject> FindSkinObjects()
        {
            IList<ISkinObject> skinObjects = new List<ISkinObject>();
            FindSkinObjects(skinObjects, this.Controls);
            return skinObjects;
        }

        private void FindSkinObjects(IList<ISkinObject> skinObjects, ControlCollection ctrls)
        {
            foreach (Control ctrl in ctrls)
            {
                if (ctrl is ISkinObject)
                    skinObjects.Add((ISkinObject)ctrl);
                if (ctrl.HasControls())
                    FindSkinObjects(skinObjects, ctrl.Controls);
            }
        }

        #endregion

    }
}
